/* hc256_lower.c
** 
** Copyright (c) 2007, Matt Hamrick, Siobhan Murtagh & Damon Orecks
** All rights reserved.
** 
** Redistribution  and  use  in  source  and  binary  forms,  with  or  without
** modification, are permitted provided that the following conditions are met:
** 
**  * Redistributions of  source code must  retain the above  copyright notice,
**    this list of conditions and the following disclaimer.
** 
**  * Redistributions in binary form must reproduce the above copyright notice,
**    this list of conditions and the following disclaimer in the documentation
**    and/or other materials provided with the distribution.
** 
**  * Neither  the  name  of the  DangerThink  Project  nor  the names  of  its
**    contributors may be used to endorse or promote products derived from this
**    software without specific prior written permission.
** 
** THIS SOFTWARE IS PROVIDED BY  THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
** AND ANY  EXPRESS OR IMPLIED WARRANTIES,  INCLUDING, BUT NOT  LIMITED TO, THE
** IMPLIED WARRANTIES  OF MERCHANTABILITY AND FITNESS FOR  A PARTICULAR PURPOSE
** ARE DISCLAIMED.  IN NO  EVENT SHALL THE  COPYRIGHT OWNER OR  CONTRIBUTORS BE
** LIABLE  FOR  ANY  DIRECT,   INDIRECT,  INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR
** CONSEQUENTIAL  DAMAGES  (INCLUDING,  BUT  NOT  LIMITED  TO,  PROCUREMENT  OF
** SUBSTITUTE GOODS  OR SERVICES;  LOSS OF USE,  DATA, OR PROFITS;  OR BUSINESS
** INTERRUPTION)  HOWEVER CAUSED  AND ON  ANY THEORY  OF LIABILITY,  WHETHER IN
** CONTRACT,  STRICT LIABILITY,  OR  TORT (INCLUDING  NEGLIGENCE OR  OTHERWISE)
** ARISING IN ANY WAY  OUT OF THE USE OF THIS SOFTWARE,  EVEN IF ADVISED OF THE
** POSSIBILITY OF SUCH DAMAGE.
**
** $Id: hc256_lower.c 20 2007-05-12 22:08:36Z matthew.hamrick $
*/

/* This is the "lower half" of the hc256 cipher. This is the guts of
** the encryption algorithm. We don't worry about memory allocation,
** endianness, or error reporting. We just manipulate bits.
*/

/* Macro Definitions */
#define rotr( x, n ) ( ( ( x ) >> ( n ) ) | ( ( x ) << ( 32 - ( n ) ) ) )
#define minux( x, y ) ( ( ( x ) - ( y ) ) % 1024 )
#define g1( x, y ) ( ( rotr( ( x ), 10 ) ) ^ ( rotr( ( y ), 23 ) ) ) + q[ ( ( x ) ^ ( y ) ) % 1024 ]
#define g2( x, y ) ( ( rotr( ( x ), 10 ) ) ^ ( rotr( ( y ), 23 ) ) ) + p[ ( ( x ) ^ ( y ) ) % 1024 ]
#define h1( x ) ( \
		  q[           ( x )         & 0xFF   ] + \
		  q[ 256 + ( ( ( x ) >>  8 ) & 0xFF ) ] + \
		  q[ 512 + ( ( ( x ) >> 16 ) & 0xFF ) ] + \
		  q[ 768 + ( ( ( x ) >> 24 ) & 0xFF ) ] )

#define h2( x ) ( \
		  p[           ( x )         & 0xFF   ] + \
		  p[ 256 + ( ( ( x ) >>  8 ) & 0xFF ) ] + \
		  p[ 512 + ( ( ( x ) >> 16 ) & 0xFF ) ] + \
		  p[ 768 + ( ( ( x ) >> 24 ) & 0xFF ) ] )

#define f1( x ) ( rotr( ( x ), 7 )  ^ rotr( ( x ), 18 ) ^ ( ( x ) >>  3 ) )

#define f2( x ) ( rotr( ( x ), 17 ) ^ rotr( ( x ), 19 ) ^ ( ( x ) >> 10 ) )

/* File Includes */
#include "portable.h"
#include "hc256_lower.h"

/* Static Prototypes */

/* Function Definitions */

/* This function initializes the state of the sboxes based on the values in
** the IV and the key. We assume that the p, q, data, counter and left values
** have been initialized to their proper starting values (i.e. zero).
** Initializing the cipher means:
**   * Copying the key into the lower 8 words of the w array
**   * Copying the iv into the next 8 words of the w array
**   * Iterate through the remaining words in w, generating each element from
**     the ones that come previously.
**   * Copying words  512 - 1535 into the cipher context as the P table
**   * Copying words 1536 - 2559 into the cipher context as the Q table
**   * Running the cipher forward 4096 steps without generating output
** 
** Note that we assume the caller has provided a 2560 word array for w. Note
** also that since each call to hc256_lower_advance generates 16 words of
** output, calling it 256 times is equivalent to running the cipher forward
** 4096 steps.
*/

/* Actually... I just noticed that we only need to save the previous 16 entries
** of state. So we could use a circular buffer, copying the from w into the p
** and q buffers after we generate each entry.
**
** todo: modify hc256_lower_init() to use a circular buffer for w
*/

void hc256_lower_init( hc256 *cipher, uint32_t *w ) {
  uint32_t i;

  memcpy( &( w[0] ), cipher->key, 32 );
  memcpy( &( w[8] ), cipher->iv,  32 );

  for( i = 16; i < 2560; i++ ) {
    w[i] = f2( w[ i-2 ] ) + w[ i-7 ] + f1( w[ i-15 ] ) + w[ i-16 ] + i;
  }

  memcpy( cipher->p, & ( w[ 512] ), 4096 );
  memcpy( cipher->q, & ( w[1536] ), 4096 );

  for( i = 0 ; i < 256 ; i++ ) {
    hc256_lower_advance( cipher );
    cipher->counter += 64;
  }

  cipher->counter = 0;
  cipher->left    = 0;
}

/* This function generates the "lower level" key stream. Since HC-256 is a 
** cipher based on the manipulation of unsigned integers, we store the
** internal state as uint32_t's. We also output uint32_t's. Now..
** the interesting part here is that the length field represents the size of
** the output buffer in bytes. Yikes! We do this to make sure the cipher
** counter is properly updated.
**
** Note that we do not output individual bytes with this function. We always
** output 32 bit words. You can ask for a number of bytes of output that is not
** a multiple of four, but you'll not get it. Instead, you'll get the number of
** bytes rounded up to the nearest multiple of 4. If you need to get individual
** bytes of output, use the hc256_keystream() function from the hc256.c file.
*/
void hc256_lower_keystream( hc256 *cipher, uint32_t *output, uint32_t length, uint32_t *bytes_written ) {

  uint32_t i;
  uint32_t j;

  do {

    for( j = 0, i = 0; i < length; i++ ) {
      if( cipher->left == 0 ) {
	hc256_lower_advance( cipher );
      }

      if( 0 == ( cipher->counter % 4 ) ) {
	output[ j ] = cipher->data[ ( cipher->counter & 0x3F ) >> 2 ];
	j++;
      }

      cipher->counter ++;
      cipher->left --;
    }

    if( NULL != bytes_written ) {
      *bytes_written = length;
    }

  } while( 0 );

}

/* this routine generates the next 16 words (64 bytes) to be used by the cipher.
*/

void hc256_lower_advance( hc256 *cipher ) {

  uint32_t index, i, j;

  uint32_t *p = cipher->p;
  uint32_t *q = cipher->q;
  uint32_t *s = cipher->data;

  i = ( cipher->counter >> 2 ) & 0x3FFFFFFF;

  for( index = 0; index < 16; index++, i++ ) {
    j = i % 1024;
    if( ( i % 2048 ) < 1024 ) {
      p[ j ] += p[ minux( j, 10 ) ] + g1( p[ minux( j, 3 ) ], p[ minux( j, 1023 ) ] ) ;
      s[ index ] = h1( p[ minux( j, 12 ) ] ) ^ p[ j ];
    } else {
      q[ j ] += q[ minux( j, 10 ) ] + g2( q[ minux( j, 3 ) ], q[ minux( j, 1023 ) ] ) ;
      s[ index ] = h2( q[ minux( j, 12 ) ] ) ^ q[ j ];
    }
  }
  
  cipher->left = 64;
}
